<template>
  <div class="effect-info">
    <div class="panel-split"></div>
    <div class="panel-body">
      <div class="panel-body-left">
        <div
          class="sidebar-item"
          v-for="item in mapCategory"
          :key="item.key"
          :class="item.code === activeKey ? 'active' : ''"
          @click="() => setActive(item)"
        >
          <span>{{ item.title }}</span>
        </div>
      </div>
      <div class="panel-body-right">
        <div class="grid-wrap">
          <div
            class="grid-item"
            :class="{
              active: selEffect && list.effectId && list.effectId === selEffect.effectId,
            }"
            v-for="(list, index) in dataList"
            :key="index"
            @click="effectChange(list)"
          >
            <div class="icon-wrap">
              <img
                v-if="list.quoteUrl || list.effCover"
                class="icon"
                :src="retFilePath(list.effCover || list.quoteUrl)"
                alt=""
              />
              <SvgIcon v-if="!list.effectId" icon-class="ic_plus" />
              <el-popover
                v-if="list.effectId && list.effectType === 4"
                :ref="setPopoverRef"
                placement="bottom"
                :width="100"
                popper-class="more-popover"
                :show-arrow="false"
                trigger="hover"
              >
                <template #reference>
                  <div class="more-wrap" @click.stop>
                    <SvgIcon icon-class="more" />
                  </div>
                </template>
                <ul class="operation-ul">
                  <li class="operation-li edit" @click="effectEdit(list)">编辑</li>
                  <el-popconfirm
                    title="是否删除?"
                    popper-class="dark-confirm"
                    width="186px"
                    placement="bottom"
                    :icon="WarnIcon"
                    @confirm="effectDelete(list)"
                  >
                    <template #reference>
                      <li class="operation-li delete">删除</li>
                    </template>
                  </el-popconfirm>
                </ul>
              </el-popover>
              <div v-if="list.effectId && list.effectType === 7" class="more-wrap">
                <SvgIcon icon-class="ic_删除" @click="effectDelete(list)" />
              </div>
            </div>
            <div class="title points" :title="list.effectName">{{ list.effectName }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- 粒子编辑器 -->
  <ParticleSetting
    v-if="particleSettingVisible"
    :json="editJson"
    :effect="selEffect"
    @close-handle="particleSettingClose"
  />
  <!-- 打点模式按钮 -->
  <div v-if="sceneStore.effectDotState" class="dot-wrap">
    <el-button type="primary" @click="exitDotMode">已开启打点模式，ESC退出打点模式</el-button>
  </div>
  <!-- 插入图片 -->
  <ChoosePic
    v-if="choosePicVisible"
    v-model="choosePicVisible"
    :upload="true"
    @close-handle="choosePicClose"
  />
  <RoadPreSetting
    v-if="onAddRoadEffect"
    v-model:form="roadPreSettingForm"
    v-model:visible="onAddRoadEffect"
  />
</template>

<script setup lang="ts">
import { provide } from 'vue';
import { useSceneStore } from '@/store/scene';
import {
  getService,
  addPanelTag,
  destroyLayer,
  operateInvalidPoi,
  destroyOrbitControl,
} from '@/service';
import { round, cloneDeep } from 'lodash';
import { messageUtil } from '@jl/element-plus/utils';
// import ParticleSetting from './particle-setting.vue';
import ParticleSetting from '../particle-edit/index.vue';
import ChoosePic from '@/components/choose-pic.vue';
import ChooseResource from '@/components/choose-resource.vue';
import { getEffectList, createEffect, deleteEffect } from '@/api/scene';
import { useRequest } from '@jl/common/composable';
import { retFilePath } from '@/utils';
import RoadPreSetting from './road-pre-setting.vue';
import { addPoiEffect } from './composables/addPoiEffect';
import { addParticleEffect } from './composables/addParticleEffect';
import { addGltfModelEffect } from './composables/addGltfModelEffect';
import { addFakeParticleSystemEffect } from './composables/addFakeParticleSystemEffect';
import { addPathEffect } from './composables/addPathEffect';
import { addPathRegionEffect } from './composables/addPathRegionEffect';
import WarnIcon from '@/components/icon/warn/index.vue';

defineOptions({
  name: 'EffectPanel',
});

const { run, data } = useRequest<any, API.Scene.IEffectItem[]>(getEffectList, []);

const mapCategory = [
  {
    key: 'poi',
    title: 'POI点',
    code: 1,
  },
  {
    key: 'gltfmodel',
    title: '模型特效',
    code: 2,
  },
  {
    key: 'parameter',
    title: '参数化特效',
    code: 3,
  },
  {
    key: 'particle',
    title: '粒子特效',
    code: 4,
  },
  {
    key: 'path',
    title: '路径',
    code: 5,
  },
  {
    key: 'regionProfile',
    title: '区域轮廓',
    code: 6,
  },
  {
    key: 'picture',
    title: '图片库',
    code: 7,
  },
];

const keyword = ref('');
const activeKey = ref<number>(1);
const sceneStore = useSceneStore();
const resizing = ref<boolean>(false);
const targetPanel = ref<any>(null);
const choosePicVisible = ref<boolean>(false);

const particleSettingVisible = ref<boolean>(false);

const setActive = (item: any) => {
  const { cimInstance } = window;
  activeKey.value = item.code;
  exitDotMode();
  run({ params: { effType: item.code } });
};

const editJson = ref<string>('');

const effectData = ref<API.Scene.IEffectItem[]>([]);

const dataList = computed(() => {
  return effectData.value.filter(
    (item: API.Scene.IEffectItem) =>
      item.effectType === activeKey.value && item.effectName.indexOf(keyword.value) > -1
  );
});

const selEffect = ref<API.Scene.IEffectItem | null>(null);
provide('selEffect', selEffect);

const { addPoi } = addPoiEffect(selEffect);
const { addParticle } = addParticleEffect(selEffect);
const { addGltfmodel } = addGltfModelEffect(selEffect);
const { addFakeParticleSystem } = addFakeParticleSystemEffect(selEffect);

const { addPath, stopRoadPath, roadPreSettingForm, onAddRoadEffect, addPathState } = addPathEffect(
  selEffect,
  exitDotMode
);
const { addRegionPath, stopRegionPath } = addPathRegionEffect(selEffect, exitDotMode);
const popoverRefs = [] as any;

onMounted(() => {
  run({ params: { effType: 1 } });
  window.addEventListener('keydown', escClose);
});

onBeforeUnmount(() => {
  const { cimInstance } = window;
  cimInstance.api.endDrawLabel();
  resizing.value = false;
  targetPanel.value = null;
  selEffect.value = null;
  sceneStore.specialEffectVisible = false;
  sceneStore.effectDotState = false;
  exitDotMode();
  // 此处对于drawlabel类型无效点进行处理
  operateInvalidPoi();
  (document.getElementById('cesiumContainer') as any).removeEventListener('click', mapClick);
  window.removeEventListener('keydown', escClose);
  // 取消特效编辑模式
  cimInstance.api.cancelEdit();
});

function setPopoverRef(el: any) {
  if (el) {
    popoverRefs.push(el);
  }
}

// 关闭popover
function closePopover() {
  popoverRefs.forEach((v: any) => v.hide());
}

function particleSettingClose(json?: string) {
  particleSettingVisible.value = false;
  if (!json) return;
  run({ params: { effType: 4 } });
  editJson.value = '';
}

function effectChange(item: API.Scene.IEffectItem) {
  const { cimInstance } = window;
  stopRoadPath();
  stopRegionPath();
  sceneStore.effectTemporaryAttr = null;
  sceneStore.poiEffectTemporaryLayernames = [];
  selEffect.value = item;
  if (item.effectType === 1) {
    // 开启打点模式
    sceneStore.effectDotState = true;
    addPoi();
    return;
  }
  if (item.effectType === 4) {
    if (!item.effectId) {
      editJson.value = '';
      particleSettingVisible.value = true;
    } else {
      // 开启打点模式
      sceneStore.effectDotState = true;
    }
    return;
  }
  if (item.effectType === 5) {
    // 开启打点模式
    sceneStore.effectDotState = true;
    addPath();
    return;
  }
  if (item.effectType === 6) {
    // 开启打点模式
    sceneStore.effectDotState = true;
    addRegionPath();
    return;
  }
  if (item.effectType === 7) {
    if (!item.effectId) {
      choosePicVisible.value = true;
    }
    return;
  }
  sceneStore.effectDotState = true;
}

function exitDot() {
  const { cimInstance } = window;
  selEffect.value = null;
  sceneStore.effectDotState = false;
  sceneStore.effectTemporaryAttr = null;
  sceneStore.poiEffectTemporaryLayernames = [];
  cimInstance.api.endDrawLabel();
  stopRoadPath();
  stopRegionPath();
  operateEmptyLayer();
  onAddRoadEffect.value = false;
  addPathState.value = 'NONE';
  // 存在3轴则删除3轴
  if (sceneStore.selLayer) {
    destroyOrbitControl(sceneStore.selLayer);
  }
}

function exitDotMode() {
  const { cimInstance } = window;
  exitDot();
}

function escClose(event?: any) {
  if (event && event.keyCode !== 27) {
    return;
  }
  if (!sceneStore.effectDotState) {
    return;
  }
  exitDotMode();
}

function mapClick(e: any) {
  const { cimInstance } = window;
  if (!selEffect.value) return;
  const clickPosition: any = cimInstance.api.screenToDegreesHeight({
    x: e.clientX,
    y: e.clientY,
  });
  if (!clickPosition) return;
  if (clickPosition[2] < 0) {
    clickPosition[2] = 0;
  }
  if (selEffect.value?.effectType === 4) {
    addParticle(clickPosition);
    return;
  }
  if (selEffect.value?.effectType === 2) {
    addGltfmodel(clickPosition);
    return;
  }
  if (selEffect.value?.effectType === 3) {
    addFakeParticleSystem(clickPosition);
  }
}

function effectEdit(item: API.Scene.IEffectItem) {
  editJson.value = item.configJson;
  selEffect.value = item;
  particleSettingVisible.value = true;
  closePopover();
}
function effectDelete(item: API.Scene.IEffectItem) {
  closePopover();
  deleteEffect({ params: { effId: item.effectId } }).then(() => {
    messageUtil.success('删除成功');
    if (selEffect.value && selEffect.value.effectId === item.effectId) {
      selEffect.value = null;
      exitDot();
    }
    run({ params: { effType: activeKey.value } });
  });
}

function choosePicClose() {
  choosePicVisible.value = false;
  if (activeKey.value === 7) {
    run({ params: { effType: 7 } });
  }
}

// 对于空图层进行处理
function operateEmptyLayer() {
  const { cimInstance } = window;
  for (let i = sceneStore.layerList.length - 1; i >= 0; i--) {
    if (sceneStore.layerList[i].type === 'drawlabel') {
      const isEmpty = cimInstance.api.getGraphicsNumber(sceneStore.layerList[i].layerName);
      if (isEmpty === 0) {
        destroyLayer(sceneStore.layerList[i]);
        sceneStore.layerList.splice(i, 1);
        continue;
      }
    }
  }
}

watch(
  () => sceneStore.effectDotState,
  () => {
    if (sceneStore.effectDotState) {
      (document.getElementById('cesiumContainer') as any).addEventListener('click', mapClick);
    } else {
      (document.getElementById('cesiumContainer') as any).removeEventListener('click', mapClick);
    }
  }
);

watch(
  () => data.value,
  () => {
    effectData.value = cloneDeep(data.value).map((item: any) => {
      return { ...item, popover: false };
    });
    if (activeKey.value === 4) {
      effectData.value.unshift({
        organizeId: '',
        effectId: '',
        effectType: 4,
        effectName: '新增粒子特效',
        effDesp: '',
        effCover: '',
        quoteUrl: '',
        configJson: '',
        createTime: '',
        logicMark: 0,
      });
      return;
    }
    if (activeKey.value === 7) {
      effectData.value.unshift({
        organizeId: '',
        effectId: '',
        effectType: 7,
        effectName: '上传图片',
        effDesp: '',
        effCover: '',
        quoteUrl: '',
        configJson: '',
        createTime: '',
        logicMark: 0,
      });
    }
  },
  {
    deep: true,
  }
);
</script>

<style lang="less">
.more-popover {
  min-width: auto !important;
  background: rgba(10, 11, 13, 0.96) !important;
  border: 1px solid rgba(151, 151, 151, 0.3) !important;
  padding: 12px 5px !important;

  .operation-ul {
    .operation-li {
      text-align: center;
      height: 32px;
      line-height: 32px;
      margin-bottom: 2px;
      font-size: 14px;
      cursor: pointer;

      &.edit {
        color: #0560fd;
      }

      &.delete {
        color: #ff5454;
      }

      &:hover {
        background: fade(#33373f, 32%);
      }
    }
  }
}
</style>
<style lang="less" scoped>
.effect-info {
  height: 100%;
  .panel-split {
    height: 10px;
    background-color: rgb(23, 26, 31);
  }

  .panel-body {
    display: flex;
    height: calc(100% - 10px);

    .panel-body-left {
      width: 98px;
      background: #14161a;
      overflow-y: auto;

      .sidebar-item {
        width: 100%;
        padding: 15px 0px 15px 15px;
        font-weight: 400;
        color: #ffffff;
        font-size: 14px;
        // text-align: center;
        cursor: pointer;

        &.active {
          color: var(--el-color-primary);
          background: #0a0b0d;
        }
      }
    }

    .panel-body-right {
      flex: 1;
      padding: 20px 20px 20px 16px;
      overflow-y: auto;

      .grid-wrap {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        column-gap: 20px;
        row-gap: 20px;

        .grid-item {
          display: flex;
          flex-direction: column;
          align-items: center;
          cursor: pointer;

          .icon-wrap {
            position: relative;
            width: 100px;
            height: 84px;
            background: #202329;
            border-radius: 4px;
            border: 1px solid transparent;
            overflow: hidden;

            .svg-icon {
              font-size: 42px;
              margin-right: 0px;
              position: absolute;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
            }

            .more-wrap {
              position: absolute;
              right: 0;
              bottom: 0;
              width: 30px;
              height: 20px;
              background: fade(#0560fd, 80%);
              border-top-left-radius: 10px;

              .svg-icon {
                font-size: 16px;
              }
            }
          }

          .icon {
            width: 100%;
            height: 100%;
          }

          .title {
            width: 100px;
            margin-top: 10px;
            text-align: center;
          }

          &.active {
            .icon-wrap {
              border-color: blue;
            }
          }
        }
      }
    }
  }
  height: 100%;
}

.dot-wrap {
  position: fixed;
  left: 50%;
  top: 130px;
  transform: translateX(-50%);
  .el-button {
    --el-button-hover-border-color: fade(#0560fd, 80%);
    --el-button-hover-bg-color: fade(#0560fd, 80%);
    height: 36px;
    border-radius: 18px;
    font-size: 16px;
  }
}
</style>
